package cz.gps;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.os.Environment;
import android.provider.Settings;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.TimeZone;
import java.util.logging.Level;
import java.util.logging.Logger;

public class MainActivity extends Activity
{

    private Date beginTime;
    private Date actualTime;
    private double distance = 0;
    private TextView distanceText;
    private TextView altitudeText;
    private TextView timeText;
    private TextView satelliteText;
    private TextView statusText;
    private TextView speedText;
    private Button clearButton;
    private Button saveButton;
    private Button stopButton;
    private boolean record = false;
    private final double radius = 6371000;
    private Calendar calendar = Calendar.getInstance();
    List<LocationPoint> list = new LinkedList<LocationPoint>();
    private SaveFileDialog dialog;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle icicle)
    {
        super.onCreate(icicle);
        setContentView(R.layout.main);
        distanceText = (TextView) findViewById(R.id.distanceText);
        altitudeText = (TextView) findViewById(R.id.altitudeText);
        satelliteText = (TextView) findViewById(R.id.satelliteText);
        statusText = (TextView) findViewById(R.id.statusText);
        speedText = (TextView) findViewById(R.id.actualSpeedText);
        satelliteText.setText("");
        timeText = (TextView) findViewById(R.id.timeText);
        clearButton = (Button) findViewById(R.id.clearButton);
        saveButton = (Button) findViewById(R.id.saveButton);
        stopButton = (Button) findViewById(R.id.stopButton);
        beginTime = new Date();//TODO jenom pro testovani, pak to musi byt po zmacknuti start
        calendar.setTimeZone(TimeZone.getTimeZone("PST"));
        //locationListener.onStatusChanged("", LocationProvider.OUT_OF_SERVICE, null);

        final LocationManager manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER))
        {
            buildAlertMessageNoGps();
        }

        saveButton.setOnClickListener(new OnClickListener()
        {

            public void onClick(View view)
            {

                dialog = new SaveFileDialog(MainActivity.this);
                dialog.show();
                dialog.getSaveButton().setOnClickListener(new OnClickListener()
                {

                    public void onClick(View view)
                    {
                        if (dialog.getFileName().equals(""))
                        {
                            AlertDialog ad = new AlertDialog.Builder(MainActivity.this).create();
                            ad.setMessage("Zadejte prosím jméno souboru");
                            ad.setButton("OK", new DialogInterface.OnClickListener()
                            {

                                public void onClick(DialogInterface dialog, int which)
                                {
                                    return;
                                }
                            });
                            ad.show();

                        } else
                        {
                            saveGPSFile(dialog.getFileName());
                            dialog.cancel();
                        }
                    }
                });
                dialog.getCancelButton().setOnClickListener(new OnClickListener()
                {

                    public void onClick(View view)
                    {
                        dialog.cancel();
                    }
                });
            }//
        });

        clearButton.setOnClickListener(new OnClickListener()
        {

            public void onClick(View view)
            {
                list.clear();
                beginTime = new Date();
                distance = 0;
                clearText();

            }
        });

        stopButton.setOnClickListener(new OnClickListener()
        {

            public void onClick(View view)
            {
                record = !record;
                if (record)
                {
                    stopButton.setText("Pozastavit záznam");
                } else
                {
                    stopButton.setText("Spustit záznam");
                }
            }
        });

        LocationManager locationManager;
        String context = Context.LOCATION_SERVICE;
        locationManager = (LocationManager) getSystemService(context);
        String provider = LocationManager.GPS_PROVIDER;
        Location location = locationManager.getLastKnownLocation(provider);
        //updateWithNewLocation(location);
        if (location != null)
        {
            list.add(new LocationPoint(location.getLatitude(),
                    location.getLongitude(), location.getAltitude(),
                    location.getSpeed(), new Date()));
        }
        locationManager.requestLocationUpdates(provider, 2000, 10, locationListener);
        clearText();
    }

    private void saveGPSFile(String fileName)
    {
        String lat, lng, alt, time, speed;
        Format formater = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss'Z'");
        fileName += ".gpx";
        fileName=fileName.replace(" ", "_");
        fileName=fileName.replace(":", "_");
        try
        {
            File root = Environment.getExternalStorageDirectory();
            if (root.canWrite())
            {
                File dir = new File("/sdcard/Runmeter/");
                if (!dir.exists())
                {
                    dir.mkdir();
                }
                File gpxfile = new File(root, "/Runmeter/" + fileName);
                FileWriter gpxwriter = new FileWriter(gpxfile);
                BufferedWriter out = new BufferedWriter(gpxwriter);
                out.write("<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?> "
                        + "<?xml-stylesheet type=\"text/xsl\" href=\"details.xsl\"?> "
                        + "<gpx version=\"1.0\" creator=\"Locus Android\" "
                        + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
                        + "xmlns=\"http://www.topografix.com/GPX/1/0\" "
                        + "xmlns:topografix=\"http://www.topografix.com/GPX/Private/TopoGrafix/0/1\" "
                        + "xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0"
                        + " http://www.topografix.com/GPX/1/0/gpx.xsd "
                        + "http://www.topografix.com/GPX/Private/TopoGrafix/0/1 "
                        + "http://www.topografix.com/GPX/Private/TopoGrafix/0/1/topografix.xsd\">"
                        + "<trk><name><![CDATA[2011-10-09 09:28:39]]></name> <trkseg>");
                for (LocationPoint p : list)
                {
                    lat = String.valueOf(p.lat);
                    lng = String.valueOf(p.lng);
                    alt = String.valueOf(p.alt);
                    speed = String.valueOf(p.speed);
                    calendar.setTime(p.time);
                    //time = String.valueOf(calendar.get(Calendar.YEAR)) + "-" + String.valueOf(calendar.get(Calendar.MONTH) + 1)
                    //      + "-" + String.valueOf(calendar.get(Calendar.DATE)) + "T" + String.valueOf(calendar.get(Calendar.HOUR_OF_DAY))
                    //     + ":" + String.valueOf(calendar.get(Calendar.MINUTE)) + ":" + String.valueOf(calendar.get(Calendar.SECOND)) + "Z";
                    time = formater.format(p.time);
                    out.write("<trkpt lat=\"" + lat + "\" lon=\"" + lng
                            + "\"><ele>" + alt + "</ele>"
                            + "<speed>" + speed + "</speed>"
                            + "<time>" + time
                            + "</time></trkpt>");

                }
                out.write("</trkseg> </trk> </gpx>");
                out.close();
            }
        } catch (IOException ex)
        {
            statusText.setText(ex.getMessage());
            Logger.getLogger(MainActivity.class.getName()).log(Level.SEVERE, null, ex);
        }


    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event)
    {
        //boolean finish;
        if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0)
        {
            final AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setMessage("Opravdu skončit?").setCancelable(false).setPositiveButton("Ano", new DialogInterface.OnClickListener()
            {

                public void onClick(@SuppressWarnings("unused") final DialogInterface dialog, @SuppressWarnings("unused") final int id)
                {
                    finish();
                    //return super.onKeyDown(keyCode, event);
                }
            }).setNegativeButton("Ne", new DialogInterface.OnClickListener()
            {

                public void onClick(final DialogInterface dialog, @SuppressWarnings("unused") final int id)
                {
                    dialog.cancel();
                }
            }).setNeutralButton("Minimalizovat", new DialogInterface.OnClickListener()
            {

                public void onClick(DialogInterface di, int i)
                {
                    moveTaskToBack(false);
                }
            });
            final AlertDialog alert = builder.create();
            alert.show();
            return true;
        }

        return super.onKeyDown(keyCode, event);
    }

    private void buildAlertMessageNoGps()
    {
        final AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage("Vaše GPS je zřejmě vypnutá, chcete ji zapnout?").setCancelable(false).setPositiveButton("Ano", new DialogInterface.OnClickListener()
        {

            public void onClick(@SuppressWarnings("unused") final DialogInterface dialog, @SuppressWarnings("unused") final int id)
            {
                startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
            }
        }).setNegativeButton("Ne", new DialogInterface.OnClickListener()
        {

            public void onClick(final DialogInterface dialog, @SuppressWarnings("unused") final int id)
            {
                dialog.cancel();
            }
        });
        final AlertDialog alert = builder.create();
        alert.show();
    }

    private void clearText()
    {
        distanceText.setText("vzdálenost: 0");
        timeText.setText("čas: 0");
        altitudeText.setText("výška: 0");
        statusText.setText("Hledám GPS satelity");

    }

    private void calculateDistance()
    {
        int size = list.size();
        if (size >= 2)
        {
            LocationPoint point1 = list.get(size - 2);
            LocationPoint point2 = list.get(size - 1);
            double lat1 = Math.toRadians(point1.lat);
            double lat2 = Math.toRadians(point2.lat);
            double dLat = Math.abs(lat1 - lat2);
            double dLng = Math.toRadians(point1.lng - point2.lng);
            double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
                    + Math.sin(dLng / 2) * Math.sin(dLng / 2) * Math.cos(lat1) * Math.cos(lat2);
            double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
            double d = radius * c;
            distance += d;
            printLabels();
        }

    }

    private void printLabels()
    {
        long time = actualTime.getTime() - beginTime.getTime();
        calendar.setTime(new Date(time));
        String s = "čas: " + calendar.get(Calendar.HOUR_OF_DAY) + "h:" + calendar.get(Calendar.MINUTE) + "min";
        timeText.setText(s);
        s = "vzdálenost: " + distance;
        distanceText.setText(s);
        s = "výška: " + list.get(list.size() - 1).alt;
        altitudeText.setText(s);
        s = "rychlost: " + list.get(list.size() - 1).speed;
        speedText.setText(s);
    }
    private final LocationListener locationListener = new LocationListener()
    {

        public void onLocationChanged(Location location)
        {
            if (record)
            {
                //updateWithNewLocation(location);
                //satelliteText.setText(satelliteText.getText() + "|");
                actualTime = new Date();
                list.add(new LocationPoint(location.getLatitude(), location.getLongitude(), location.getAltitude(), location.getSpeed(), actualTime));
                calculateDistance();
            }
        }

        public void onStatusChanged(String string, int i, Bundle bundle)
        {
            String status = "";
            switch (i)
            {
                case LocationProvider.AVAILABLE:
                    status = "dostupny";
                    break;
                case LocationProvider.OUT_OF_SERVICE:
                    status = "nedostupny";
                    break;
                case LocationProvider.TEMPORARILY_UNAVAILABLE:
                    status = "docasne nedostupny";
                    break;
            }
            statusText.setText("status: " + string + " je " + status);
        }

        public void onProviderEnabled(String string)
        {
            //throw new UnsupportedOperationException("Not supported yet.");
        }

        public void onProviderDisabled(String string)
        {
            //throw new UnsupportedOperationException("Not supported yet.");
        }
    };
}
